package com.hqd.jjvm.instructions.compare;

import com.hqd.jjvm.instructions.AbstractInstruction;
import com.hqd.jjvm.instructions.InstructionType;
import com.hqd.jjvm.rtda.JThread;
import com.hqd.jjvm.rtda.obj.JObject;

public class CompareInstruction extends AbstractInstruction {

    public CompareInstruction(JThread jThread) {
        super(jThread);
    }

    @Override
    public void execute(InstructionType instructionType) {
        switch (instructionType) {
            case LCMP: {
                long num2 = popOperandStackLongVal();
                long num1 = popOperandStackLongVal();
                if (num1 > num2) {
                    pushOperandStackVal(1);
                } else if (num1 == num2) {
                    pushOperandStackVal(0);
                } else {
                    pushOperandStackVal(-1);
                }
                break;
            }
            case FCMPL: {
                float num2 = popOperandStackFloatVal();
                float num1 = popOperandStackFloatVal();
                if (Double.isNaN(num1) || Double.isNaN(num2)) {
                    pushOperandStackVal(-1);
                } else {
                    if (num1 > num2) {
                        pushOperandStackVal(1);
                    } else if (num1 == num2) {
                        pushOperandStackVal(0);
                    } else {
                        pushOperandStackVal(-1);
                    }
                }
                break;
            }
            case FCMPG: {
                float num2 = popOperandStackFloatVal();
                float num1 = popOperandStackFloatVal();
                if (Double.isNaN(num1) || Double.isNaN(num2)) {
                    pushOperandStackVal(1);
                } else {
                    if (num1 > num2) {
                        pushOperandStackVal(1);
                    } else if (num1 == num2) {
                        pushOperandStackVal(0);
                    } else {
                        pushOperandStackVal(-1);
                    }
                }
                break;
            }
            case DCMPL: {
                double num2 = popOperandStackFloatVal();
                double num1 = popOperandStackFloatVal();
                if (Double.isNaN(num1) || Double.isNaN(num2)) {
                    pushOperandStackVal(-1);
                } else {
                    if (num1 > num2) {
                        pushOperandStackVal(1);
                    } else if (num1 == num2) {
                        pushOperandStackVal(0);
                    } else {
                        pushOperandStackVal(-1);
                    }
                }
                break;
            }
            case DCMPG: {
                double num2 = popOperandStackFloatVal();
                double num1 = popOperandStackFloatVal();
                if (Double.isNaN(num1) || Double.isNaN(num2)) {
                    pushOperandStackVal(1);
                } else {
                    if (num1 > num2) {
                        pushOperandStackVal(1);
                    } else if (num1 == num2) {
                        pushOperandStackVal(0);
                    } else {
                        pushOperandStackVal(-1);
                    }
                }
                break;
            }
            case IFEQ: {
                int num = popOperandStackIntVal();
                if (num == 0) {
                    int offer = parseAndReadValU2(false);
                    offerIncrement(offer);
                } else {
                    parseAndReadValU2();
                }
                break;
            }
            case IFNE: {
                int num = popOperandStackIntVal();
                if (num != 0) {
                    short offer = (short) parseAndReadValU2(false).intValue();
                    offerIncrement((int) offer);
                } else {
                    parseAndReadValU2();
                }
                break;
            }
            case IFLT: {
                int num = popOperandStackIntVal();
                if (num < 0) {
                    int offer = parseAndReadValU2(false);
                    offerIncrement(offer);
                } else {
                    parseAndReadValU2();
                }
                break;
            }
            case IFGE: {
                int num = popOperandStackIntVal();
                if (num >= 0) {
                    int offer = parseAndReadValU2(false);
                    offerIncrement(offer);
                } else {
                    parseAndReadValU2();
                }
                break;
            }
            case IFGT: {
                int num = popOperandStackIntVal();
                if (num > 0) {
                    int offer = parseAndReadValU2(false);
                    offerIncrement(offer);
                } else {
                    parseAndReadValU2();
                }
                break;
            }
            case IFLE: {
                int num = popOperandStackIntVal();
                if (num <= 0) {
                    int offer = parseAndReadValU2(false);
                    offerIncrement(offer);
                } else {
                    parseAndReadValU2();
                }
                break;
            }
            case IF_ICMPEQ: {
                int num1 = popOperandStackIntVal();
                int num2 = popOperandStackIntVal();
                if (num1 == num2) {
                    int offer = parseAndReadValU2(false);
                    offerIncrement(offer);
                } else {
                    parseAndReadValU2();
                }
                break;
            }
            case IF_ICMPNE: {
                int num1 = popOperandStackIntVal();
                int num2 = popOperandStackIntVal();
                if (num1 != num2) {
                    int offer = parseAndReadValU2(false);
                    offerIncrement(offer);
                } else {
                    parseAndReadValU2();
                }
                break;
            }
            case IF_ICMPLT: {
                int num2 = popOperandStackIntVal();
                int num1 = popOperandStackIntVal();
                if (num1 < num2) {
                    int offer = parseAndReadValU2(false);
                    offerIncrement(offer);
                } else {
                    parseAndReadValU2();
                }
                break;
            }
            case IF_ICMPGE: {
                int num2 = popOperandStackIntVal();
                int num1 = popOperandStackIntVal();
                if (num1 >= num2) {
                    int offer = parseAndReadValU2(false);
                    offerIncrement(offer);
                } else {
                    parseAndReadValU2();
                }
                break;
            }
            case IF_ICMPGT: {
                int num2 = popOperandStackIntVal();
                int num1 = popOperandStackIntVal();
                if (num1 > num2) {
                    int offer = parseAndReadValU2(false);
                    offerIncrement(offer);
                } else {
                    parseAndReadValU2();
                }
                break;
            }
            case IF_ICMPLE: {
                int num2 = popOperandStackIntVal();
                int num1 = popOperandStackIntVal();
                if (num1 <= num2) {
                    int offer = parseAndReadValU2(false);
                    offerIncrement(offer);
                } else {
                    parseAndReadValU2();
                }
                break;
            }
            case IF_ACMPEQ: {
                JObject o1 = popOperandStackRefVal();
                JObject o2 = popOperandStackRefVal();
                if (o1 == o2) {
                    int offer = parseAndReadValU2(false);
                    offerIncrement(offer);
                } else {
                    parseAndReadValU2();
                }
                break;
            }
            case IF_ACMPNE: {
                JObject o1 = popOperandStackRefVal();
                JObject o2 = popOperandStackRefVal();
                if (o1 != o2) {
                    if (o1 != null && !o1.equals(o2)) {
                        int offer = parseAndReadValU2(false);
                        offerIncrement(offer);
                    } else {
                        parseAndReadValU2();
                    }
                } else {
                    parseAndReadValU2();
                }
                break;
            }
        }
    }
}
